package org.nViron.nvData;

//~--- non-JDK imports --------------------------------------------------------

import org.nViron.nvCommon.nvPosition;
import org.nViron.nvParams.nvContextCalculator;
import org.nViron.nvParams.nvContextParamMgr.CONTEXTPARAM;
import org.nViron.nvParams.nvContextValueCache;
import org.nViron.nvParams.nvVizParamMgr.VIZPARAM;
import org.nViron.nvRender.nvRenderer;
import org.nViron.nvSim.nvObject;

/**
 * Abstraction for geo locatable data entity that has context values
 * @author Roland Haring <p>
 * <script type="text/javascript" src="http://www.ohloh.net/p/376434/widgets/project_basic_stats.js"></script>
 */
public abstract class nvDataEntity extends nvObject implements nvContextCalculator, nvDataEntitySimilarity {
    private nvContextValueCache contextValueCache = new nvContextValueCache(this);

    public nvDataEntity(nvDataEntityMgr entityMgr) {
        super(entityMgr);
    }

    public float getContextValue(CONTEXTPARAM param) {
        return contextValueCache.getContextValue(param);
    }

    public nvDataEntityMgr getEntityMgr() {
        return (nvDataEntityMgr) getObjectMgr();
    }

    public abstract nvPosition getPosition();

    public float getSimilarityTo(nvDataEntity other) {
        float sum = 0.0f;

        // euclidian distance
        for (int i = 0; i < CONTEXTPARAM.values().length; i++) {
            if (CONTEXTPARAM.values()[i] == CONTEXTPARAM.INVALID) {
                continue;
            }

            sum += (this.getContextValue(CONTEXTPARAM.values()[i]) - other.getContextValue(CONTEXTPARAM.values()[i]))
                   * (this.getContextValue(CONTEXTPARAM.values()[i]) - other.getContextValue(CONTEXTPARAM.values()[i]));
        }

        // normalized to 1.0f
        return (float) Math.sqrt(sum) / (float) Math.sqrt(CONTEXTPARAM.values().length - 1);
    }

    public float getSimilarityTo(nvDataEntity other, CONTEXTPARAM contextParam) {
        return 1.0f - Math.abs(getContextValue(contextParam) - other.getContextValue(contextParam));
    }

    public float getSimilarityTo(nvDataEntity other, VIZPARAM vizParam) {
        return 1.0f - Math.abs(getVizValue(vizParam) - other.getVizValue(vizParam));
    }

    public float getVizValue(VIZPARAM param) {
        return getEntityMgr().getSimulator().getParamBindingMgr().getValueFor(param, this);
    }

    public void render(nvRenderer renderer) {
        renderer.renderDataEntity(this);
    }

    protected void updateAllContextValues() {
        contextValueCache.updateAllContextValues(getEntityMgr().getSimulator().getContextParamMgr());
    }

    public void updateContextValue(CONTEXTPARAM param) {
        contextValueCache.updateContextValue(param);
    }
}



